package com.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import com.google.common.collect.Lists;
import com.auth.model.system.SysMenu;
import com.auth.mapper.SysMenuMapper;
import com.auth.model.system.SysRoleMenu;
import com.auth.service.SysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.auth.service.SysRoleMenuService;
import com.auth.utils.MenuHelperUtils;
import com.auth.vo.system.AssginMenuVo;
import com.auth.vo.system.MetaVo;
import com.auth.vo.system.RouterVo;
import exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author tang
 * @since 2023-07-16
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    private final SysMenuMapper sysMenuMapper;
    private final SysRoleMenuService sysRoleMenuService;
    public SysMenuServiceImpl(SysMenuMapper sysMenuMapper,
                              SysRoleMenuService sysRoleMenuService) {
        this.sysMenuMapper = sysMenuMapper;
        this.sysRoleMenuService = sysRoleMenuService;
    }

    @Override
    public List<SysMenu> findNodes() {
        List<SysMenu> allMenu = baseMapper.selectList(null);
        // 构建前端树形结构
        return MenuHelperUtils.builderTree(allMenu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeMenuById(Long id) {
        try {
            if (null == id) {
                return ;
            }
            // 判断当前菜单是否有子菜单有则不能删除
            LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMenu::getParentId, id);
            Long selectCount = baseMapper.selectCount(queryWrapper);
            // 有子菜单
            if (selectCount.intValue() > 0) {
                throw new BusinessException(501, "菜单不能删除");
            }
            baseMapper.deleteById(id);
        } catch (Exception e) {
            e.printStackTrace();
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SysMenu> findMenuByRoleId(Long roleId) {
        try {
            // 查询所有status为1的菜单
            LambdaQueryWrapper<SysMenu> queryMenu = new LambdaQueryWrapper<>();
            queryMenu.eq(SysMenu::getStatus, 1);
            List<SysMenu> allMenu = baseMapper.selectList(queryMenu);

            // 根据角色id查询角色菜单关系表中的角色id对应的所有菜单id
            LambdaQueryWrapper<SysRoleMenu> queryRoleMenu = new LambdaQueryWrapper<>();
            queryRoleMenu.eq(SysRoleMenu::getRoleId, roleId);
            List<SysRoleMenu> allRoleMenu = sysRoleMenuService.list(queryRoleMenu);

            // 根据获取菜单id，获取对应的菜单对象
            List<Long> menuIds = allRoleMenu.stream()
                    .map(SysRoleMenu::getMenuId)
                    .collect(Collectors.toList());

            allMenu.forEach(menu -> menu.setSelect(menuIds.contains(menu.getId())));

            return MenuHelperUtils.builderTree(allMenu);
        } catch (Exception e) {
            e.printStackTrace();
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ArrayList<>(0);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doAssign(AssginMenuVo assginMenuVo) {
        try {

            LambdaQueryWrapper<SysRoleMenu> query = new LambdaQueryWrapper<>();
            query.eq(SysRoleMenu::getRoleId, assginMenuVo.getRoleId());
            sysRoleMenuService.remove(query);

            List<SysRoleMenu> saves = Lists.newArrayList();
            List<Long> menuIds = assginMenuVo.getMenuIdList();
            for (Long menuId : menuIds) {
                if (null == menuId) {
                    continue;
                }
                final SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(assginMenuVo.getRoleId());
                sysRoleMenu.setMenuId(menuId);
                saves.add(sysRoleMenu);
            }
            sysRoleMenuService.saveBatch(saves);
        } catch (Exception e) {
            e.printStackTrace();
            //手工回滚异常
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        List<SysMenu> sysMenus = null;
        // 判断是否是管理员，如果是管理员则查询所有菜单列表
        if (userId == 1) {
            sysMenus = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>()
                    .eq(SysMenu::getStatus, 1)
                    .orderByDesc(SysMenu::getSortValue));
        } else {
            sysMenus = baseMapper.findMenuListByUserId(userId);
        }
        // 将查询出来的结果构建前端的路由信息
        return builderRouter(MenuHelperUtils.builderTree(sysMenus));
    }

    public List<RouterVo> builderRouter(List<SysMenu> treeMenus) {
        final List<RouterVo> routerVos = Lists.newArrayList();
        treeMenus.stream().forEach(treeMenu -> {
            List<SysMenu> children = treeMenu.getChildren();

            final RouterVo routerVo = new RouterVo();
            routerVo.setPath(getRouterPath(treeMenu));
            routerVo.setComponent(treeMenu.getComponent());
            routerVo.setMeta(new MetaVo(treeMenu.getName(), treeMenu.getIcon()));

            // 获取下一层菜单
            if (treeMenu.getType() == 1) {
                // 加载隐藏路由
                treeMenu.getChildren()
                        .stream()
                        .filter(item -> StringUtils.isNotBlank(item.getComponent()))
                        .collect(Collectors.toList())
                        .forEach(hiddenMenu -> {

                            final RouterVo hiddenVo = new RouterVo();
                            hiddenVo.setPath(getRouterPath(hiddenMenu));
                            hiddenVo.setComponent(hiddenMenu.getComponent());
                            hiddenVo.setHidden(true);
                            hiddenVo.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));

                            routerVos.add(hiddenVo);
                        });
            } else {
                if (CollectionUtils.isNotEmpty(children)) {
                    if (children.size() > 0) {
                        routerVo.setAlwaysShow(true);
                    }
                    routerVo.setChildren(builderRouter(children));
                }
            }
            routerVos.add(routerVo);
        });
        return routerVos;
    }

    public String getRouterPath(SysMenu treeMenu) {
        String routerPath = "/" + treeMenu.getPath();
        if (treeMenu.getParentId() != 0) {
            routerPath = treeMenu.getPath();
        }
        return routerPath;
    }

    @Override
    public List<String> findUserPermsByUserId(Long userId) {
        List<SysMenu> sysMenus = null;
        // 判断是否是管理员，如果是管理员查询所有按钮列表
        if (userId == 1) {
            sysMenus = baseMapper.selectList(new LambdaQueryWrapper<SysMenu>()
                    .eq(SysMenu::getStatus, 1)
                    .orderByDesc(SysMenu::getSortValue));
        } else {
            sysMenus = baseMapper.findMenuListByUserId(userId);
        }
        // 将查询出来的结果返回
        return sysMenus.stream()
                .filter(item -> item.getType() == 2)
                .map(SysMenu::getPerms)
                .collect(Collectors.toList());
    }
}
